package com.terrace.web.shiro;

import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.terrace.web.constant.GlobalsConstant;
import com.terrace.db.system.mapper.entity.Permission;
import com.terrace.db.system.mapper.entity.Role;
import com.terrace.db.system.mapper.entity.User;
import com.terrace.core.common.model.UserInfo;
import com.terrace.db.system.service.PermissionService;
import com.terrace.db.system.service.UserService;

/**
 * 用户访问权限授权
 * @author jiangyg
 *
 */
public class UserRealm extends AuthorizingRealm {
	
	/**
	 * 日志
	 */
	private static final Logger logger = LoggerFactory.getLogger(UserRealm.class);
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private PermissionService permissionService;
	
	/**
	 * 认证回调函数,登录时调用。
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		logger.debug("用户[" + token.getUsername() + "]登录认证");
		User user = userService.selectUserByAccount(token.getUsername());
		if (user != null) {
			UserInfo userInfo = new UserInfo(user.getId(), user.getUserAccount(), user.getUserName());
			//设置用户session
			Session session =SecurityUtils.getSubject().getSession();
			session.setAttribute(GlobalsConstant.USER_SESSION_KEY, userInfo);
			return new SimpleAuthenticationInfo(userInfo, user.getUserPwd(), ByteSource.Util.bytes(user.getSalt()), getName());
		} else {
			throw new UnknownAccountException("用户名[" + token.getUsername() + "]不存在");
		}
	}

	/**
	 * 鉴权回调函数，提取当事人的角色和权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		UserInfo userInfo = (UserInfo) principals.getPrimaryPrincipal();
		logger.debug("执行用户[" + userInfo.getUserAccount() + "]授权查询回调函数");;
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		
		// 查询用户角色
		List<Role> roles = userService.selectRoleByUserId(userInfo.getUserId());
		// 赋予用户角色
		for (Role role : roles) {
			authorizationInfo.addRole(role.getRoleCode());
		}
		logger.debug("用户[" + userInfo.getUserAccount() + "]授予的角色：[" + authorizationInfo.getRoles() + "]");
		
		// 查询用户权限
		List<Permission> permissions = permissionService.selectPermissionsByUserId(userInfo.getUserId());
		// 赋予权限
		for (Permission permission : permissions) {
			if (StringUtils.isNotBlank(permission.getPermiCode())) {
				authorizationInfo.addStringPermission(permission.getPermiCode());
			}
		}
		logger.debug("用户[" + userInfo.getUserAccount() + "]授予的权限：[" + authorizationInfo.getStringPermissions() + "]");
		
		return authorizationInfo;
	}
	
	@PostConstruct
	public void initCredentialsMatcher() {
		// 该句作用是重写shiro的密码验证，让shiro用我自己的验证
		setCredentialsMatcher(new CustomCredentialsMatcher());
	}
	
}
